package com.gmail.yesguxun.tumblr.content;

import java.io.File;
import java.util.ArrayList;

import junit.framework.Assert;
import com.gmail.yesguxun.tumblr.Constant;
import com.gmail.yesguxun.tumblr.ui.ViewBigPhotoActivity;
import com.gmail.yesguxun.util.EventBusAsync;
import com.gmail.yesguxun.util.EventBusEventObj;
import com.gmail.yesguxun.util.LogFactory;
import com.gmail.yesguxun.util.LogX;

public class TrContentObjectPool {
    
	static private int mContentId = 0;
	
    static TrContentObjectPool mPoolInstance = null;
    ArrayList<TrContentObject> mContents = null;
    
    private LogX mLog = LogFactory.getLogObject();
    
    private int mCursor = -1;
    
    private boolean mSyncing = false;
    
    private boolean mSyncingCancel = false;
    
    
    
    public static TrContentObjectPool getPoolInstance()
    {
        if(mPoolInstance == null)
        {
            mPoolInstance = new TrContentObjectPool();
            
            //testing
            //mPoolInstance.refreshPoolAsync();
            //mPoolInstance.refreshPool();
        }                     
        
        return mPoolInstance;
    }
    
    public static synchronized int createContentId()
    {
    	mContentId ++;
    	return mContentId;
    }
    
    
    public TrContentObjectPool()
    {
        mContents = new ArrayList<TrContentObject>();
    }

  
    public int getContentCount() {
        
        return mContents.size();
    }


    public TrContentObject getContentAt(int index) {
        
        if(index <0)
        {
            return null;
        }
        
        try{
            return mContents.get(index);
        }
        catch(Exception e)
        {
            return null;
        }
    }
    

    public TrContentObject getContentCurrent() {
        
        if(this.mCursor < 0 )
        {
            return null;
        }
        
        try{
            return mContents.get(this.mCursor);
        }
        catch(Exception e)
        {
            return null;
        }
    }


    public synchronized void  addContent(TrContentObject obj) {        
        mContents.add(obj);
        mLog.debug("tumblr", "Content Number " + this.getContentCount());
        if(this.getContentCount() == 1)
        {
        	mLog.debug("tumblr", "Sending the EVENT_FIRST_CONTENT_ADDED_TO_POOL");
            EventBusAsync.getInstance().fireEvent(new EventBusEventObj(Constant.EVENT_FIRST_CONTENT_ADDED_TO_POOL, null));
        }
        else{
        	//EventBusAsync.getInstance().fireEvent(new EventBusEventObj(Constant.EVENT_NEW_CONTENT_ADDED_TO_POOL, null));
        }
    }   
    

    public void addContent(String objUri) {
        TrContentObject obj = new TrContentObject(objUri);
        addContent(obj);
    }
    

    public void setCursor(int cursor) {
        this.mCursor = cursor;        
    }


    public int getCursor() {
        return this.mCursor;
    }


    public TrContentObject getPrevious() {
        if(getContentCount() <= 0)
        {
            return null;    
        }
        
        if(this.mCursor == -1)
        {
            this.mCursor = 0;
        }
        else
        {
            if(this.mCursor <= 0)
            {
                this.mCursor = getContentCount() - 1;
            }
            else
            {
                this.mCursor --;
            }
        }
        
        return getContentCurrent();
    }


    public TrContentObject getNext() {
    	mLog.debug("tumblr", "Pool getNext  " + getContentCount());
        if(getContentCount() <= 0)
        {
            return null;    
        }
        
        if(this.mCursor == -1)
        {
            this.mCursor = 0;
        }
        else
        {            
            if((getContentCount() - 1) > this.mCursor)
            {
                this.mCursor ++;                  
            }
            else
            {
                // Doing nothing, or we can choose to go to the first item.
                return null;
            }
        }
        
        return getContentCurrent();
    }
    
    public void likeContentAsync(final TrContentObject content)
    {
        Runnable runnable = new Runnable(){
            @Override
            public void run() {
                likeContent(content);
            }        
        };
        
        new Thread(runnable).start();
    }
    
    public void likeContent(TrContentObject content)
    {
        
        TrContentProvider cP = TrContentProvider.getProviderInstance();
        cP.likeContent(content);
    }
    
    public void authorizeAsync()
    {
    	Runnable runnable = new Runnable(){
            @Override
            public void run() {
            	authorize();
            }        
        };
        
        new Thread(runnable).start();
    }
    
    
    
    public void authorize()
    {
    	TrContentProvider cP = TrContentProvider.getProviderInstance();
    	
    	boolean result = cP.authorize();
    	EventBusAsync.getInstance().fireEvent(
    			new EventBusEventObj(Constant.EVENT_AUTHORIZATION_COMPLETE, new Boolean(result)));
    }
    
    public void refreshPoolAsync()
    {
        if(this.mSyncing)
        {
        	mLog.info("tumblr", "Ignore refreshPoolAsync there is already a sync task running");
        	return;
        }
    	
    	mLog.info("tumblr", "refreshPoolAsync to get more data, now we have: " + mContents.size());

    	
        Runnable runnable = new Runnable(){

            @Override
            public void run() {
            	refreshPoolFromEnd();
            }
            
        };
        
        new Thread(runnable).start();
    }
    
    
    public synchronized boolean refreshPool(int offset)
    {
    	TrContentProvider cP = TrContentProvider.getProviderInstance();
    	ArrayList<TrContentObject> urlList = null;
    	       
    	if(cP.isAuthorized() != true)
    	{
    	    if(cP.authorize() != true)
    	    {
    	    	return false;
    	    }
    	}
    	
    	boolean ret = false;
    	this.mSyncing = true;
    	
    	urlList = cP.refreshData(offset);
    	
    	if(urlList != null)
    	{
        	int numUrl = urlList.size();
        	
        	for(int indexUrl = 0; indexUrl < numUrl; indexUrl ++)
        	{
        		TrContentObject obj = (TrContentObject)urlList.get(indexUrl);
        		
        		try{
        			obj.downloadLocalAsync();
        		}
        		catch(Exception e)
        		{
        			mLog.info("tumblr", "Failed to download photo of url:" + obj.getPropertyString(Constant.CONTENT_PROPERTY_REMOTE_URL) + " message:" + e.getMessage());    			
        		}
        		mLog.debug("tumblr", "downloaded: " + obj.getPropertyString(Constant.CONTENT_PROPERTY_REMOTE_URL) + "  localUrl: " + obj.getURI());    		
        		
        		this.addContent(obj);
        		
        		if(this.mSyncingCancel)
        		{
        			break;
        		}
        	}
        	
        	ret = true;
    	}
    	else
    	{
    	    ret = false;
    	}
    	
    	this.mSyncing = false;
    	
    	return ret;
    }
    
    public synchronized boolean refreshPoolFromStart()
    {
        return refreshPool(0);
    }
    
    public synchronized boolean refreshPoolFromEnd()
    {
    	return refreshPool(getContentCount());
    }
    
    
    public String getLatestPostId()
    {
    	String postIdLatest = null;
    	if(getContentCount() > 0)
    	{
    		postIdLatest = this.mContents.get(0).getPropertyString(Constant.CONTENT_PROPERTY_POST_ID);
    	}
    	
    	
    	return postIdLatest;
    }


	public void clearAllContent() {
		if(this.mSyncing)
		{
			this.mSyncingCancel = true;
			while(this.mSyncing)
			{
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					Assert.assertEquals(true, false);
				}
			}
			this.mSyncingCancel = false;
		}
		this.mContents.clear();
		this.mCursor = -1;
		clearAllLocalImage();
	}
	
    
	private void clearAllLocalImage()
	{
		File dir = ViewBigPhotoActivity.getContextWrapper().getFilesDir();
		
		String[] children = dir.list();
		for (int i = 0; i < children.length; i++) {
            File file = new File(dir, children[i]);
            file.delete();
        }
	}

}
